﻿using System;
using System.Collections.Generic;
using System.Text;
//using HtmlParsingLibrary;
using System.IO;
using StockGeneral;

using System.Xml;
using System.Threading;
using System.Data.SqlClient;
using System.Security.Cryptography;
//using HttpLibrary;
using System.Net;
using System.Diagnostics;
using System.Configuration;
using System.Globalization;


namespace StockTrader.API.TradingAlgos
{
    public static class AlgoRunner
    {
        // Stock algo worker thread
        public static void Background_StockWorkerThread(object obj)
        {
            BrokerErrorCode errorCode = BrokerErrorCode.Success;
            StockAndBrokerObject stockTraderObj = (StockAndBrokerObject)obj;
            IBroker broker = stockTraderObj.broker;
            EquityStockInformation stockInfo = stockTraderObj.stockInfo;
            ITradingAlgo algo = stockTraderObj.stockAlgo;

            // Thread local params
            int threadRunCount = 0;
            int threadFailCount = 0;

            string stockCode = stockInfo.StockCode;
            string traceString;
            bool bChecked = false;
            // On program re-run, cancel any previous outstanding orders
            // BUGBUGCD: is this infinite loop necessary or try only once
            // and come out on failure
            do
            {
                errorCode = algo.Prolog();
                if (!errorCode.Equals(BrokerErrorCode.Success))
                {
                    // sleep of 30 seconds
                    Thread.Sleep(1000 * 30);
                }
            } while (!stockTraderObj.bStopThread && !errorCode.Equals(BrokerErrorCode.Success));


            while (!stockTraderObj.bStopThread)
            {

                // Main Algo
                errorCode = algo.RunCoreAlgo();

                // thread stats
                if (!errorCode.Equals(BrokerErrorCode.Success))
                {
                    threadFailCount++;
                }
                threadRunCount++;

                // Check remote control

                // TEMPTEMP: this check is currently temporary , need to place it properly to provide pause algo functionality
                // Check after every 5 minutes
                ProgramRemoteControl remoteControlValue = ProgramRemoteControl.RUN;
                int minutes = DateTime.Now.Minute;
                int seconds = DateTime.Now.Second;
                if (minutes % 5 == 1)
                {
                    bChecked = false;
                }
                if ((minutes >= 5) && (minutes % 5 == 0) && !bChecked)
                {
                    bChecked = true;
                    remoteControlValue = RemoteUtils.GetProgramRemoteControlValue();
                    // keep looping until PAUSE status is reset
                    while (remoteControlValue.Equals(ProgramRemoteControl.PAUSE))
                    {
                        traceString = string.Format("AlgoRunner: Remote Control PAUSED the Algo, sleeping for 30 seconds before rechecking\n");
                        FileTracing.TraceOut(traceString);
                        // sleep 60 seconds
                        Thread.Sleep(60000);
                        remoteControlValue = RemoteUtils.GetProgramRemoteControlValue();
                    }
                    if (remoteControlValue.Equals(ProgramRemoteControl.STOP) ||
                        remoteControlValue.Equals(ProgramRemoteControl.HIBERNATE))
                    {
                        traceString = string.Format("AlgoRunner: Remote Control issued STOP/HIBERNATE command to the Algo\n");
                        FileTracing.TraceOut(traceString);
                        break;
                    }
                }


                // Check if login problem
                if (errorCode == BrokerErrorCode.NotLoggedIn)
                {
                    FileTracing.TraceOut("AlgoRunner: " + errorCode.ToString() + " Trying to login again\n");
                    // MGOYAL: TEMP SLEEP this is for external login to do some work .
                    // External logger will have 2 minute (CheckAndLoginIfNeeded) window to complete a work before he is logged out.
                    // Sleep for a minute

                    // It means someone has stolen session, so let it be. if they need for more time then will set remote to PAUSE
                    Thread.Sleep(120000);
                    broker.LogOut();
                    errorCode = broker.CheckAndLogInIfNeeded(true);
                    continue;
                }
                else if (errorCode == BrokerErrorCode.InvalidLoginPassword || errorCode == BrokerErrorCode.ChangePassword)
                {
                    FileTracing.TraceOut("AlgoRunner: InvalidLoginPassword, Exiting");
                    //loginRetryCount++;
                    //Thread.Sleep(60000);
                    break;
                }

                
                // sleep , algo-specific 
                Thread.Sleep(algo.GetSleepTimeInMilliSecs());

            }

            errorCode = algo.Epilog();

            // Trace out Thread run stats
            // TODO: more such fancy stuff later

            traceString = string.Format("AlgoRunner: Thread Run Stats: \nTotalRuns: {0}\nFailures: {1}\nFailurePercentage: {2}",
                threadRunCount, threadFailCount, (double)(threadFailCount / (threadRunCount > 0 ? threadRunCount : 1)) * 100);

            FileTracing.TraceOut(traceString);
        }
    }
}